package com.durian.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.durian.config.ServiceException;
import com.durian.domain.DTO.ObsBookAddDTO;
import com.durian.domain.DTO.ObsBookListDTO;
import com.durian.domain.entity.ObsBook;
import com.durian.domain.entity.ObsOrderBook;
import com.durian.domain.entity.ObsShopcar;
import com.durian.enums.BookStatus;
import com.durian.mapper.ObsBookMapper;
import com.durian.mapper.ObsOrderBookMapper;
import com.durian.mapper.ObsShopcarMapper;
import com.durian.service.IObsBookService;
import com.durian.utils.PageInfoResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 书籍表 服务实现类
 *
 * @author Durian
 * @since 2023-11-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ObsBookServiceImpl extends ServiceImpl<ObsBookMapper, ObsBook> implements IObsBookService {

    @Value("${default.pageNum}")
    private Integer pageNum;

    @Value("${default.pageSize}")
    private Integer pageSize;

    private final ObsBookMapper bookMapper;

    private final ObsOrderBookMapper orderBookMapper;

    private final ObsShopcarMapper shopcarMapper;

    @Override
    public PageInfoResult<ObsBook> listBook(ObsBookListDTO bookListDTO) {

        String bookAuthor = bookListDTO.getBookAuthor();
        String bookClassify = bookListDTO.getBookClassify();
        String bookIntroduce = bookListDTO.getBookIntroduce();
        String bookName = bookListDTO.getBookName();
        String bookPrinter = bookListDTO.getBookPrinter();
        Integer bookStatus = bookListDTO.getBookStatus();
        String searchMessage = bookListDTO.getSearchMessage();
        Integer pageNum = bookListDTO.getPageNum();
        Integer pageSize = bookListDTO.getPageSize();

        LambdaQueryWrapper<ObsBook> listBookWrapper = new LambdaQueryWrapper<ObsBook>()
                .or().like(StringUtils.isNotBlank(bookAuthor), ObsBook::getBookAuthor, bookAuthor)
                .or().like(StringUtils.isNotBlank(bookClassify), ObsBook::getBookClassify, bookClassify)
                .or().like(StringUtils.isNotBlank(bookIntroduce), ObsBook::getBookIntroduce, bookIntroduce)
                .or().like(StringUtils.isNotBlank(bookName), ObsBook::getBookName, bookName)
                .or().like(StringUtils.isNotBlank(bookPrinter), ObsBook::getBookPrinter, bookPrinter)
                .or().like(StringUtils.isNotBlank(searchMessage), ObsBook::getBookAuthor, searchMessage)
                .or().like(StringUtils.isNotBlank(searchMessage), ObsBook::getBookClassify, searchMessage)
                .or().like(StringUtils.isNotBlank(searchMessage), ObsBook::getBookIntroduce, searchMessage)
                .or().like(StringUtils.isNotBlank(searchMessage), ObsBook::getBookName, searchMessage)
                .or().like(StringUtils.isNotBlank(searchMessage), ObsBook::getBookPrinter, searchMessage)
                .eq(ObjectUtils.isNotNull(bookStatus), ObsBook::getBookStatus, bookStatus);

        // 检查分页页码和大小
        if (ObjectUtils.isNull(pageNum)) {
            pageNum = this.pageNum;
        }
        if (ObjectUtils.isNull(pageSize)) {
            pageSize = this.pageSize;
        }

        PageInfo<ObsBook> pageInfo = PageHelper
                .startPage(pageNum, pageSize)
                .doSelectPageInfo(() -> bookMapper.selectList(listBookWrapper));
        return PageInfoResult.of(pageInfo);
    }

    @Override
    public List<ObsBook> listBook(String search) {
        LambdaQueryWrapper<ObsBook> listBookWrapper = new LambdaQueryWrapper<ObsBook>()
                .or(StringUtils.isNotBlank(search), i -> i
                        .or().like(ObsBook::getBookAuthor, search)
                        .or().like(ObsBook::getBookPrinter, search)
                        .or().like(ObsBook::getBookClassify, search)
                        .or().like(ObsBook::getBookIntroduce, search)
                        .or().like(ObsBook::getBookName, search));

        return bookMapper.selectList(listBookWrapper);
    }

    @Override
    @Transactional
    public void addBook(ObsBookAddDTO bookAddDTO) {

        // 新建书籍对象
        ObsBook book = new ObsBook();
        // 将添加的数据放入书籍对象
        BeanUtils.copyProperties(bookAddDTO, book);

        // 添加书籍
        int insertBook = bookMapper.insert(book);
        if (insertBook != 1) {
            log.error("添加失败！= bookMapper.insert({})", insertBook);
            throw new ServiceException("添加失败,系统错误！");
        }
    }

    @Override
    @Transactional
    public void updateBook(ObsBook book) {

        Long bookId = book.getBookId();
        String bookAuthor = book.getBookAuthor();
        String bookNumber = book.getBookNumber();
        String bookImgUrl = book.getBookImgUrl();
        String bookClassify = book.getBookClassify();
        String bookIntroduce = book.getBookIntroduce();
        String bookName = book.getBookName();
        Double bookPrice = book.getBookPrice();
        String bookPrinter = book.getBookPrinter();
        Date bookRelDate = book.getBookRelDate();
        Integer bookStock = book.getBookStock();
        BookStatus bookStatus = book.getBookStatus();

        LambdaUpdateWrapper<ObsBook> updateBookWrapper = new LambdaUpdateWrapper<ObsBook>()
                .set(StringUtils.isNotBlank(bookAuthor), ObsBook::getBookAuthor, bookAuthor)
                .set(StringUtils.isNotBlank(bookNumber), ObsBook::getBookNumber, bookNumber)
                .set(StringUtils.isNotBlank(bookClassify), ObsBook::getBookClassify, bookClassify)
                .set(StringUtils.isNotBlank(bookImgUrl), ObsBook::getBookImgUrl, bookImgUrl)
                .set(StringUtils.isNotBlank(bookIntroduce), ObsBook::getBookIntroduce, bookIntroduce)
                .set(StringUtils.isNotBlank(bookName), ObsBook::getBookName, bookName)
                .set(StringUtils.isNotBlank(bookPrinter), ObsBook::getBookPrinter, bookPrinter)
                .set(ObjectUtils.isNotNull(bookPrice), ObsBook::getBookPrice, bookPrice)
                .set(ObjectUtils.isNotNull(bookRelDate), ObsBook::getBookRelDate, bookRelDate)
                .set(ObjectUtils.isNotNull(bookStock), ObsBook::getBookStock, bookStock)
                .set(ObjectUtils.isNotNull(bookStatus), ObsBook::getBookStatus, bookStatus)
                .eq(ObsBook::getBookId, bookId);

        int updateBook = bookMapper.update(new ObsBook(), updateBookWrapper);
        if (updateBook != 1) {
            log.error("更新失败！{} = bookMapper.update({})", updateBook, updateBookWrapper.getSqlSet());
            throw new ServiceException("更新失败,系统错误！");
        }

    }

    @Override
    @Transactional
    public void removeBook(List<Long> ids) {

        ids.forEach(id -> {
            // 检查书籍是否正在被订单使用
            LambdaQueryWrapper<ObsOrderBook> orderIsUsedWrapper = new LambdaQueryWrapper<ObsOrderBook>()
                    .select(ObsOrderBook::getOrderBookId)
                    .eq(ObsOrderBook::getBookId, id);

            // 检查书籍是否正在被购物车使用
            LambdaQueryWrapper<ObsShopcar> shopcarUsedBookWrapper = new LambdaQueryWrapper<ObsShopcar>()
                    .select(ObsShopcar::getShopcarId)
                    .eq(ObsShopcar::getBookId, id);

            if (orderBookMapper.exists(orderIsUsedWrapper) ||
                    shopcarMapper.exists(shopcarUsedBookWrapper)) {
                throw new ServiceException("书籍正在被使用！无法删除");
            }
        });

        // 移除书籍
        LambdaUpdateWrapper<ObsBook> removeBookWrapper = new LambdaUpdateWrapper<ObsBook>()
                .in(ObsBook::getBookId, ids);

        int removeBook = bookMapper.delete(removeBookWrapper);

        if (removeBook <= 0) {
            log.error("移除失败！{} = bookMapper.delete({})", removeBook, removeBookWrapper.getSqlSet());
            throw new ServiceException("移除失败,系统错误！");
        }
    }
}
